import vtkPolyData from "@kitware/vtk.js/Common/DataModel/PolyData"
import vtkPoints from "@kitware/vtk.js/Common/Core/Points"
import vtkCellArray from "@kitware/vtk.js/Common/Core/CellArray"
import { BasePlugin } from "../Plugins/BasePlugin"
import { devtool } from "../devtool"
import { BaseLoader } from "./BaseLoader"

export class BdfLoader extends BaseLoader{
  url: string = ""
  // 面形结构的数据
  polyData = vtkPolyData.newInstance()
  points = vtkPoints.newInstance()
  cells = vtkCellArray.newInstance()
  origin: any
  // 记录每个索引位置对应的pointId key: pointId, value: index
  pointsIdIndexMap: any = {}
  // 记录了每个eid的索引位置 key: eid, value: index
  elementsIdIndexMap: any = {}
  // 记录了索引位置处cell对应的point的索引 key: index, value: [pointIndex1, pointIndex2, pointIndex3 ...]
  cellsIdIndexMap: any = {}
  // 记录了每个索引位置对应的cell的eid key: index, value: eid
  elementsIndexIdMap: any = {}

  cellsInfo = []
  // #start 线型结构
  // 线型结构的数据 CBAR CROD
  lineTypeData = []
  // 点索引数组
  lineTypeIndex = []
  // 线型结构的原始数据
  lineTypeOriginData = []
  // 线型结构的ID数据
  lineTypeIdArr = []
  // 线型结构的几何数据
  linePolyData = vtkPolyData.newInstance()
  linePoints = vtkPoints.newInstance()
  lineCells = vtkCellArray.newInstance()
  // #end 线型结构

  constructor(url?: string) {
    super()
    if (url) {
      this.url = url
    }
  }

  use(plugin: BasePlugin) {
    if (!this.plugins[plugin.key]) {
      this.plugins[plugin.key] = plugin
    } else {
      devtool.warn(`${plugin.name} already exist`)
    }
    return this
  }

  override parse(dataObj: any) {
    this.origin = dataObj
    this.createIdIndexMap(dataObj)
    this.createPointData(dataObj)
    this.createCellData(dataObj)
    this.polyData.setPoints(this.points)
    this.polyData.setPolys(this.cells)
    this.createLinesPolyData(this.lineTypeData)
  }

  createIdIndexMap(dataObj: any) {
    dataObj.nodeIds.map((v: number, index: number) => {
      this.pointsIdIndexMap[v] = index
    })
  }

  // * 构建顶点数据
  createPointData(dataObj: any) {
    const TMP_nodes = [...dataObj.nodes]
    const TMP_arr = new Float32Array(TMP_nodes.length).fill(0.0)
    TMP_nodes.map((v: any, index: number) => {
      TMP_arr[index] = Number(v)
    })
    this.points.setData(TMP_arr, 3)
  }

  // * 构建单元数据
  createCellData(dataObj: any) {
    const TMP_cells = [...dataObj.elements]
    // ! 因为有残缺的cell，所以需要先构建一个标记来正确的插入数据
    let count = 0
    for (let i = 0; i < TMP_cells.length; i++) {
      // ! 跳过数据残缺的cell
      if (!this.checkNodeIds(TMP_cells[i].nodeIds)) continue
      let ids_arr: number[] = []
      TMP_cells[i].nodeIds.map((id: any) => {
        ids_arr.push(this.pointsIdIndexMap[id])
      })
      // ! 把线型结构区分出来
      if (ids_arr.length === 2) {
        this.lineTypeData.push(
          dataObj.nodes[3 * ids_arr[0]],
          dataObj.nodes[3 * ids_arr[0] + 1],
          dataObj.nodes[3 * ids_arr[0] + 2],
          dataObj.nodes[3 * ids_arr[1]],
          dataObj.nodes[3 * ids_arr[1] + 1],
          dataObj.nodes[3 * ids_arr[1] + 2]
        )
        this.lineTypeIndex.push(...ids_arr)
        this.lineTypeIdArr.push(TMP_cells[i].eid)
        this.lineTypeOriginData.push(TMP_cells[i])
      } else {
        /**
         * * 因为实际的位置是count 所以此处不用i ⚡
         */
        this.elementsIdIndexMap[TMP_cells[i].eid] = count
        this.elementsIndexIdMap[count] = TMP_cells[i].eid
        this.cellsIdIndexMap[count] = ids_arr
        this.cells.insertNextCell(ids_arr)
        count += 1
      }
    }
  }

  cellIndexToId(index: number): number {
    return this.elementsIndexIdMap[`${index}`]
  }

  cellIndexToPoints(index: number): number[] {
    const points = this.cellsIdIndexMap[index]
    let r = []
    points.forEach((index: number) => {
      r.push(this.origin.nodes[3 * index])
      r.push(this.origin.nodes[3 * index + 1])
      r.push(this.origin.nodes[3 * index + 2])
    })
    return r
  }

  getCellInfoByIndex(index: number) {
    return {
      cellIndex: index,
      cellId: this.cellIndexToId(index),
      points: this.cellIndexToPoints(index),
      // pointIds: this.cellsIdIndexMap[index],
    }
  }

  getAllCellInfo() {
    const keys = Object.keys(this.cellsIdIndexMap)
    let r = []
    for (let i = 0; i < keys.length; i++) {
      r.push(this.getCellInfoByIndex(+keys[i]))
    }
    return r
  }

  // * 检查nodeId是否有数据
  checkNodeId(id: number) {
    return this.pointsIdIndexMap[id] !== undefined
  }

  // * 检查一组nodeId是否有数据
  checkNodeIds(ids: number[]) {
    return ids.every((id: number) => {
      return this.checkNodeId(id)
    })
  }

  // * 构造线型结构的聚合数据
  createLinesPolyData(points: number[]) {
    const tmp = [...points]
    this.linePoints.setData(tmp)
    this.createLinesCells(tmp.length / 6)
    this.linePolyData.setPoints(this.linePoints)
    this.linePolyData.setLines(this.lineCells)
  }

  // * 获取线型结构的聚合数据
  getLinesPolyData() {
    return this.linePolyData
  }

  private createLinesCells(n: number) {
    for (let i = 0; i < n; i++) {
      this.lineCells.insertNextCell([i * 2, i * 2 + 1])
    }
  }
  
  lineIndexToId(index:number) {
    return this.lineTypeIdArr[index]
  }
}
